package com.example.nativemedia;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ProgressBar;
import android.widget.SlidingDrawer;
import android.widget.TextView;
public class NativeMedia extends Activity {
	static final String TAG = "NativeMedia";
	private static final boolean AN_DEBUG = false;
	private static final int BLOCK_FRAME = 188;
    private static final int INTIAL_KB_BUFFER =  1880*1000;//assume 96kbps*10secs/8bits per byte
    private boolean isBufferDownloadBusy = false;
    private int indexBuffer = 1;
    private File playingBuffer1; 
	private File playingBuffer2;
	private static final String path="/mnt/sdcard/";
	private int mediaLengthInKb;
	private int mediaLengthInSeconds;
	private File downloadingMediaFile; 
	private File playingMediaFile;
	private final Handler handler = new Handler();
	private long totalKbRead = 0;
	private static int pre_totalKbRead = 0;
	private static long pre_time = 0;
	private Thread thread;
	private TextView textStreamed;
	private ProgressBar progress;
	private int mCounter;
	private int mFileSize;
	protected static final int BLOCK_SIZE = 4096;
	protected static final int BUFFER_SIZE = 4096;
	protected static final int MIN_DOWNLOAD_SIZE = BLOCK_SIZE * 100;
	protected int mDownloaded;
	protected ArrayList<DownloadThread> mListDownloadThread;
	private SurfaceView mSurfaceView1;
	private SurfaceHolder mSurfaceHolder1;
	private String mSourceString;
	VideoSink mNativeMediaPlayerVideoSink;
	VideoSink mSelectedVideoSink;
	boolean mIsPlayingStreaming = false;
	boolean created = false;
	SurfaceHolderVideoSink mSurfaceHolder1VideoSink;
	public static native void createEngine();
    public static native boolean createStreamingMediaPlayer(String filename, int type);
    public static native void setPlayingStreamingMediaPlayer(boolean isPlaying);
    public static native void shutdown();
    public static native int getDuration();
    public static native int getPosition();
    public static native void setSurface(Surface surface);
    public static native void rewindStreamingMediaPlayer();
    public static native void switchFile();
    public static native int isBufferPlaying();
    public static native int setStateBuffer(int indexBuffer, int value);
    public static native int getStateBuffer(int indexBuffer);
    /** Load jni .so on initialization */
    static {
         System.loadLibrary("native-media-jni");
    }
    
    // VideoSink abstracts out the difference between Surface and SurfaceTexture
    // aka SurfaceHolder and GLSurfaceView
    static abstract class VideoSink {

        abstract void setFixedSize(int width, int height);
        abstract void useAsSinkForNative();

    }
    static class SurfaceHolderVideoSink extends VideoSink {

        private final SurfaceHolder mSurfaceHolder;

        SurfaceHolderVideoSink(SurfaceHolder surfaceHolder) {
            mSurfaceHolder = surfaceHolder;
        }
        void setFixedSize(int width, int height) {
            mSurfaceHolder.setFixedSize(width, height);
        }
        void useAsSinkForNative() {
            Surface s = mSurfaceHolder.getSurface();
            setSurface(s);
            s.release();
        }
    }
    private void ProgressiveDownload(String url) throws IOException {
		URL mURL = new URL(url);
		HttpURLConnection conn = null;
		mFileSize = -1;
		conn = (HttpURLConnection)mURL.openConnection();
		conn.connect();
		if (conn.getResponseCode() / 100 != 2) {
            log("is not 200 Range");
			error();
			return;
        }
		
		int contentLength = conn.getContentLength();
        if (contentLength < 1) {
            log("Length < 1 ");
        	error();
        	return;
        }
        if (mFileSize == -1) {
        	mFileSize = contentLength;
        	log("File size: " + mFileSize);
        }
		int mIndex = 0;
		Buffer bfplay = new Buffer(++mIndex, 0, Buffer.BUFFER_SIZE-1, mURL);
		Buffer bfdown = new Buffer(++mIndex, bfplay.endByte()+1, bfplay.endByte()+Buffer.BUFFER_SIZE, mURL);
		bfplay.download();
		bfdown.download();
		start(1); //_fixme test Download error
		setStateBuffer(2, Buffer.FULL);
		bfplay = bfdown;
		while(bfplay.endByte () < mFileSize){
			while(isBufferPlaying() != mIndex); 
			bfplay = bfdown;
			//Sleep();//_fixme sleep
			if((mFileSize - bfplay.endByte()) > Buffer.BUFFER_SIZE)
				bfdown= new Buffer(++mIndex, bfplay.endByte()+1, bfplay.endByte()+Buffer.BUFFER_SIZE, mURL);
			else
				bfdown= new Buffer(++mIndex, bfplay.endByte()+1, mFileSize, mURL);
			bfdown.download();
			setStateBuffer(mIndex, Buffer.FULL);
			log("Buffer Download Full: " + mIndex);
		}
		log("play video finished");
	}
    private void Sleep(){
		for(long j=0;j< 10000000;j++)
			for(int i=0;i<100;i++);
    }
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.tutorial3);
		textStreamed = (TextView)findViewById(R.id.text_kb_streamed);
		progress     =  (ProgressBar)findViewById(R.id.progress_bar);
		createEngine();
		mSourceString = "/mnt/sdcard/test2.MP4";
		mSourceString = "/mnt/sdcard/bbb.MP4";
		mSourceString = "http://ebop.elcomhcm.com:9000/vod/HD720/Bedtime.Stories.720p.BluRay.x264-REFiNED.mp4";
		mSourceString = "http://ebop.elcomhcm.com:9000/vod/HD720/Race.To.Witch.Mountain.2009.720p.BluRay.DTS.x264-EPiK.mp4";
		mSourceString = "http://ebop.elcomhcm.com:9000/vod/HD720/_b-septic.mp4";
		mSourceString = "http://www.pocketjourney.com/downloads/pj/video/famous.3gp";
		mSourceString = "http://172.16.9.8/film/ggg.mp4";
		mSourceString = "http://ebop.elcomhcm.com:9000/vod/HD720/Lost.MAT.TICH.S06.01.mp4";
		mSurfaceView1 = (SurfaceView) findViewById(R.id.SurfaceView);
        mSurfaceHolder1 = mSurfaceView1.getHolder();
        mSurfaceHolder1.addCallback(new SurfaceHolder.Callback() {
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                Log.v(TAG, "surfaceChanged format=" + format + ", width=" + width + ", height="
                        + height);
            }
            public void surfaceCreated(SurfaceHolder holder) {
                setSurface(holder.getSurface());
                if (mSurfaceHolder1VideoSink == null) {
                    mSurfaceHolder1VideoSink = new SurfaceHolderVideoSink(mSurfaceHolder1);
                }
                mSelectedVideoSink = mSurfaceHolder1VideoSink;
                if(AN_DEBUG){
                	mSourceString = "/mnt/sdcard/bbb.mp4";
                	start(0);
                	
                }else{
	                if(mSourceString.contains("http://")){ // server
		                Runnable r = new Runnable() {   
		        	        public void run() {   
		        	            try {   
		        	            	//pre_time = System.currentTimeMillis();
		        	            	ProgressiveDownload(mSourceString);
		        	            } catch (IOException e) {
		        	            	Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mSourceString, e);
		        	            	return;
		        	            }   
		        	        }   
		        	    };   
		        	    thread = new Thread(r);
		        	    thread.start();
	                }else{								    // local file
	                	start(0);
	                }
                }
            }
            
            public void surfaceDestroyed(SurfaceHolder holder) {
                Log.v(TAG,  "surfaceDestroyed");
            }
        });
        
        mSurfaceView1.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				switchFile();
			}
		});
	}
	void start(int type){
		//create Mediaplayer to getDuration
		 if (!created) {
            if (mNativeMediaPlayerVideoSink == null) {
                mSelectedVideoSink.useAsSinkForNative();
                mNativeMediaPlayerVideoSink = mSelectedVideoSink;
            }
            if (mSourceString != null) {
                created = createStreamingMediaPlayer(mSourceString,type);
            }
        }
        if (created) {
        	Log.d(TAG,"created");
            mIsPlayingStreaming = !mIsPlayingStreaming;
            setPlayingStreamingMediaPlayer(mIsPlayingStreaming);
        }else{
        	Log.d(TAG,"cannot create");
        }
       //startPlayProgressUpdater();
    
	}
	private File createFile(String ss){
		File file = new File(ss);
		if (file.exists()) {
			file.delete();
		}
		file.setExecutable(true, false);
		file.setWritable(true, false);
		file.setReadable(true, false);
		return file;
	}
	private void log(String ss){
		Log.d("nna", ss);
	}
	private void error(){
		Log.e("nna","error");
	}

	

	

	private void checkSpeedDownload(){
//		if((pre_totalKbRead != totalKbRead) && ((System.currentTimeMillis()-pre_time) != 0 )){
//			int mSpeed = (totalKbRead-pre_totalKbRead)*1000/(int)(System.currentTimeMillis()-pre_time);
//			log("Speed:"+String.valueOf(mSpeed) + " kbyte/s");
//			pre_time = System.currentTimeMillis();
//			pre_totalKbRead = totalKbRead;
//		}
		
	}

	 public void moveFile(File	oldLocation, File	newLocation)
		throws IOException {
			//log("moveFile");
			if ( oldLocation.exists( )) {
				BufferedInputStream  reader = new BufferedInputStream( new FileInputStream(oldLocation) );
				BufferedOutputStream  writer = new BufferedOutputStream( new FileOutputStream(newLocation, false));
	            try {
			        byte[]  buff = new byte[8192];
			        int numChars;
			        while ( (numChars = reader.read(  buff, 0, buff.length ) ) != -1) {
			        	writer.write( buff, 0, numChars );
			        }
	            } catch( IOException ex ) {
					throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath());
	            } finally {
	                try {
	                    if ( reader != null ){                    	
	                    	writer.close();
	                        reader.close();
	                    }
	                } catch( IOException ex ){
					    Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); 
					}
	            }
	        } else {
				throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
	        }
	 }


}
